package mac.eventRecognizer.pedlParser;

import mac.types.parserTypes.*;
import mac.eventRecognizer.interpreter.*;

public class ASTCondition extends SimpleNode {
  static final int AND = 0;	// Boolean AND
  static final int OR = 1;	// Boolean OR
  static final int XOR = 2;	// Bitwise XOR
  static final int NOT = 3;
  static final int INM = 4;
  static final int EQ = 5;
  static final int NEQ = 6;
  static final int LT = 7;
  static final int LE = 8;
  static final int GT = 9;
  static final int GE = 10;
  static final int INSTANCEOF = 11;
  static final int PARENTHESIS = 12;
  static final int CONSTANT = 13;
  /** This type defines event definition.
   *  ex> condition IC = RRC.train_X > RRC.cross_x 
   *                ~~ */
  static final int ASSIGNMENT = 14;

  protected int op;
  protected String name;
  protected Object oldValue;

  ASTCondition(int id) {
    super(id);
  }

  public int getOp() {
    return op;
  }
  public String getName() {
    return name;
  }
  public void setOp(int o) {
    op =o;
  }
  public void setName(String n) {
    name = n;
  }

  public Object evaluate() {
      if( mark) {
	  //System.err.println(this); 
	  return value;
      }				// If this node is already evaluated, 
				// it just returns value.
      mark = true;

      oldValue = value;

      switch(op) {
	  /* A child must be ASTCondition or ASTExpression of type
	   * VARIABLE
	   * METHOD
	   * VALUE
	   * ARRAY
	   * CAST
	   */
	  case ASSIGNMENT :
	  {
	      SymtabEntry se = null;

	      Node child = jjtGetChild(0);
	      value = child.evaluate();

	      // Mark this condition is updated
	      se = (SymtabEntry)EventRecognizer.symbolTbl.get(name);
	      se.setUpdated();
	      //System.err.println(EventRecognizer.symbolTbl);
	      //System.err.println(se);

	      break;
	  }
	  case PARENTHESIS :
	  {
	      Node child = jjtGetChild(0);
	      value = child.evaluate();
	      break;
	  }
	  case NOT:
	  {
	      Node child = jjtGetChild(0);
	      value = new Boolean(((Boolean)(child.evaluate())).booleanValue());
	      break;
	  }

	  /* Children must be ASTCondition or ASTExpression of type
	   * VARIABLE
	   * METHOD
	   * VALUE
	   * ARRAY
	   * CAST
	   */
	  case AND :
	  {
	      boolean  tempResult = true;
	      for(int i=0; i < jjtGetNumChildren(); i++) {
		  /*System.err.println("AND's " + i + " th child:" + 
			  jjtGetChild(i) +  jjtGetChild(i).getMark() + 
			  ((ASTCondition)jjtGetChild(i)).op); */
		  tempResult = tempResult & 
		      ((Boolean)jjtGetChild(i).evaluate()).
		      booleanValue();
	      }
	      value = new Boolean(tempResult);
	      break;
	  }
	  case OR :
	  {
	      boolean  tempResult = false;
	      for(int i=0; i < jjtGetNumChildren(); i++) {
		  /*System.err.println("OR's " + i + " th child:" + 
			  jjtGetChild(i) +  jjtGetChild(i).getMark() + 
			  ((ASTCondition)jjtGetChild(i)).op); */
		  tempResult = tempResult | 
		      ((Boolean)jjtGetChild(i).evaluate()).
		      booleanValue();
	      }
	      value = new Boolean(tempResult);
	      break;
	  }


	  /* This node has 2 children which are ASTCondition 
	   * or ASTExpression of type
	   * VARIABLE
	   * METHOD
	   * VALUE
	   * ARRAY
	   * CAST
	   */
	  case GT :
	  case GE :
	  case LT : 
	  case LE : 
	  case EQ :
	  case NEQ :
	  {
	      Object leftValue = jjtGetChild(0).evaluate();
	      Object rightValue = jjtGetChild(1).evaluate();

	      value = new Boolean(ASTConditionAux.evalRelation
		      (leftValue,rightValue,op)); 
	      break;
	  }

	  case CONSTANT : 	
	  {
	      break;
	  }
	  case XOR :
	  case INM :
	  case INSTANCEOF:
	      System.err.println("XOR,INM,INSTANCEOF are not yet implemented.");
	      break;

	  default: System.err.println("Incorrect type " + op + " is detected while "
			   + this + " is evaluated!");
      }
  //    System.err.println(this); 
      return value;
  }


  


  public String tString() {
    String s= null;
    String s2= null;
    Object realValue = null;
    SymtabEntry se = null;

    switch (op) {
      case AND: s =  "Condition: and";break; 
      case OR: s =  "Condition: or";break; 
      case XOR: s =  "Condition: xor";break; 
      case NOT: s =  "Condition: not";break; 
      case INM: s =  "Condition: in method";break; 
      case EQ: s =  "Condition: equal";break; 
      case NEQ: s =  "Condition: not equal";break; 
      case LT: s =  "Condition: less than";break; 
      case LE: s =  "Condition: less than or equal";break; 
      case GT: s =  "Condition: greater than";break; 
      case GE: s =  "Condition: greater than or equal";break; 
      case INSTANCEOF: s =  "Condition: instance of";break; 
      case PARENTHESIS: s =  "Condition: parenthesis";break; 
      case CONSTANT: s =  "Condition: constant";break; 
      case ASSIGNMENT: s =  "Condition: assignment";break; 
      default: s =  "Condition: error";break; 
    }
      if(value instanceof SymtabEntry) {
	  se = (SymtabEntry)value;
	  if( ((String)(se.getType())).equals("_macType")) {
	      realValue = ((Node)(se.getValue())).getValue(); 
	  } else {
	      realValue = se.getValue();
	  }
      } else {
	  realValue = value;
      }

      return s + "(name:"+ name + ",value:" 
	    + realValue + ",mark:" + mark + ")" ;
  }
  public Object getOldValue() { return oldValue;}
}
